/*
 * Copyright 2008 - 2009 Lars Heuer (heuer[at]semagia.com). All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.semagia.atomico.server.impl.restlet.resources;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.restlet.data.Method;
import org.restlet.data.Status;
import org.restlet.representation.RepresentationInfo;
import org.restlet.representation.Variant;
import org.restlet.resource.ResourceException;

import com.semagia.atomico.MediaType;
import com.semagia.atomico.dm.impl.DefaultAuthor;
import com.semagia.atomico.server.FeedHandlerRegistry;
import com.semagia.atomico.server.IConfiguration;
import com.semagia.atomico.server.dm.impl.DefaultFeed;
import com.semagia.atomico.server.feed.IOutputAwareFeedHandler;

/**
 * Common superclass for resources which provide feeds.
 * 
 * @author Lars Heuer (heuer[at]semagia.com) <a href="http://www.semagia.com/">Semagia</a>
 * @version $Rev: 90 $ - $Date: 2010-10-21 23:34:45 +0000 (Thu, 21 Oct 2010) $
 */
abstract class AbstractFeedBaseResource extends AbstractBaseResource {

    /**
     * Represents the default media type of feed resources.
     */
    private static final Variant _VARIANT_ATOM = new ImmutableVariant(MediaTypeUtils.toRestletMediaType(MediaType.ATOM_XML));

    /**
     * The <tt>variants</tt> field of {@link org.restlet.resource.Resource}
     * is private, this class must mimic it.
     */
    private List<Variant> _variants;

    /**
     * Creates a feed resource.
     */
    protected AbstractFeedBaseResource() {
        super();
    }

    /* (non-Javadoc)
     * @see org.restlet.resource.ServerResource#getPreferredVariant(org.restlet.data.Method)
     */
    @Override
    public Variant getPreferredVariant(Method method) {
        if (Method.GET.equals(method)) {
            return _VARIANT_ATOM;
        }
        return super.getPreferredVariant(method);
    }

    /* (non-Javadoc)
     * @see org.restlet.resource.ServerResource#getInfo(org.restlet.representation.Variant)
     */
    @Override
    protected RepresentationInfo getInfo(Variant variant)
            throws ResourceException {
        return new RepresentationInfo(variant, new Date(lastModification()));
    }

    /**
     * The feed variants depend on the registered feed handlers.
     * <p>
     * Subclasses may not change that, therefor "final".
     * </p>
     * 
     * @see org.restlet.resource.Resource#getVariants()
     */
    @Override
    public final List<Variant> getVariants(Method method) {
        if (_variants == null) {
            _variants = new ArrayList<Variant>();
            if (Method.GET.equals(method)) {
                for (MediaType mediaType: getMediaTypes()) {
                    _variants.add(new Variant(MediaTypeUtils.toRestletMediaType(mediaType)));
                }
            }
        }
        return _variants;
    }

    /* (non-Javadoc)
     * @see com.semagia.atomico.server.impl.restlet.resources.AbstractBaseResource#getMediaTypes()
     */
    //@Override
    protected Iterable<MediaType> getMediaTypes() {
        return FeedHandlerRegistry.getMediaTypes();
    }

    /**
     * Sets the author information to the specified feed.
     *
     * @param feed The feed.
     */
    protected final void applyAuthorInfo(DefaultFeed<?> feed) {
        IConfiguration config = getConfiguration();
        feed.setAuthor(new DefaultAuthor(config.getAuthorName(), 
                config.getAuthorEmail(), config.getAuthorIRI()));
    }

    /**
     * Returns a feed handler which is able to write syntax for a 
     * particular media type.
     *
     * @param variant A variant with an associated media type.
     * @return A feed handler for the media type.
     * @throws ResourceException If no feed handler is available for the
     *          the media type of the variant.
     */
    protected static final IOutputAwareFeedHandler makeFeedHandler(final Variant variant) throws ResourceException {
        IOutputAwareFeedHandler handler = FeedHandlerRegistry
                .createFeedHandler(MediaTypeUtils.toAtomicoMediaType(variant.getMediaType()));
        if (handler == null) {
            throw new ResourceException(Status.CLIENT_ERROR_NOT_ACCEPTABLE,
                    "No feed available for media type " + variant.getMediaType());
        }
        return handler;
    }

}
